/**
 * @file hiddenType.c
 * @brief Implementa le funzioni per gestire le strutture dati definite
 * in hiddenType.h il corrispettivo header.
 *
 * Sono presenti le funzioni per gestire la struttura HiddenType.
 *
 * @date Mar 16, 2012
 * @author Francesco Corvino
 */
#include "hiddenType.h"

/**
 * @brief Inizializza un oggetto HiddenType.
 *
 * Gli altri attributi dell'oggetto vengono inizializzati a NULL.
 *
 * @param ht puntatore all'oggetto da inizializzare
 * @param data dati da nascondere
 * @param size dimensione dei dati
 */
void HiddenType_init(HiddenType*ht,void * data, size_t size){
	ht->size = size;
	ht->destroy = NULL;
	ht->interpretfnc = NULL;
	if(size==0){ // nessun dato specificato
		ht->hiddentype = NULL;
	} else {
		ht->hiddentype = malloc(size);
		/// @note Allocazione per i dati fallita non gestita
		if(ht->hiddentype==NULL) {
			ht->hiddentype = data;
			return;
		}
		memcpy(ht->hiddentype, data,size);
	}
}

void* HiddenType_change(HiddenType*ht,void *data, size_t size){
	void* temp = ht->hiddentype;
	if(size==0){ // nessun dato specificato
		ht->hiddentype = NULL;
	} else {
		ht->hiddentype = malloc(size);
		/// @note Allocazione per i dati fallita non gestita
		if(ht->hiddentype==NULL) {
			ht->hiddentype = data;
			return temp;
		}
		memcpy(ht->hiddentype, data,size);
	}
	return temp;
}

/**
 * Dealloca la memoria allocata da un oggetto HiddenType.
 *
 * @param ht hiddenType da eliminare.
 */
void HiddenType_destroy(HiddenType *ht){
	if(ht->destroy!=NULL){
		(*ht->destroy)(ht->hiddentype);
	}
	if(ht->hiddentype!=NULL) free(ht->hiddentype);
}

void * HiddenType_executeInterpreter(HiddenType* ht, void * context){
	if(ht->interpretfnc==NULL) return NULL;
	return (*ht->interpretfnc)(ht->hiddentype, context);
}

/**
 * @brief Esecutore dell'interpretazione delle informazioni presenti in un <code>HiddenType</code>.
 * Interpretatore utilizzato nel caso di dichiarazioni del tipo
 * <code>HiddenType = String | char* (*fn)(void * context) </code>
 * @param value valore dell'hidden type
 * @param context contesto dell'hidden type: se impostato a NULL definisce di non utilizzare la funzione interpretatrice.
 */
char* getHiddenTypeToString(void * value, void * context){
	if(context==NULL) {
		return (char*) value;
	} // interpreta il campo value come un puntatore a funzione char* (*fnc)(void*)
	char* (*some_func)() = (char* (*)(void*)) value;
	return (char*) (*some_func)(context);
}
